<?php

namespace App\Models\CacheModel\ai_chat_room;

use App\Models\Api\BaseCache;
use AstroTool\Cache\CacheManage;

class AiChatRecordDetails extends BaseCache
{
    protected $table = 'ai_chat_room.ai_chat_record_details';

    protected $cacheModel = 'ai_chat_room.chat_details';

    /**
     * 对话 写入数据
     * @param int $chatId
     * @param array $datas
     * @return array
     */
    public function SaveData(int $chatId, array $datas)
    {
        try
        {
            $resData = [];
            $pid = 0;
            foreach ($datas as $dataItem)
            {
                if ($pid && $dataItem['type'] === 1)    //  1=>APP消息 2=>用户发送消息
                {   // 系统发消息
                    $dataItem['pid'] = $pid;
                }
                $dataItem['extend'] = json_encode($dataItem['extend'], JSON_UNESCAPED_UNICODE);
                $dataItem['result_data'] = $dataItem['result_data'] ? json_encode($dataItem['result_data'], JSON_UNESCAPED_UNICODE) : '';
                $id = $this->insertGetId($dataItem);
                $dataItem['id'] = (int)$id;
                if ($dataItem['type'] === 2)    //  1=>APP消息 2=>用户发送消息
                {
                    $pid = $dataItem['id'];
                }
                $dataItem['extend'] = json_decode($dataItem['extend'], true);
                $dataItem['result_data'] = $dataItem['result_data'] ? json_decode($dataItem['result_data'], true) : [];
                // list ID添加
                $this->listDataAdd($chatId, [$dataItem['id'] => $dataItem['id']]);
                $resData[] = $dataItem;
            }
        }
        catch (\Exception $e)
        {
            \think\Log::write(__CLASS__ . ' => ' . __FUNCTION__ . '()异常：' . $e->getMessage() . '失败信息：' . $e->getFile() . ':' . $e->getLine(), 'error', true);
            return [];
        }
        return $resData;
    }

    /**
     * 更新数据
     * @param int $chatDetailId
     * @param array $data
     * @return bool
     */
    public function UpdateData(int $chatDetailId, array $data)
    {
        try
        {
            $data['update_time'] = time();
            $this->where(['id' => $chatDetailId])->update($data);

            CacheManage::getInstance()->setCacheConfig($this->cacheModel, $chatDetailId)->rmCache();
            return true;
        }
        catch (\Exception $e)
        {
            \think\Log::write(__CLASS__ . ' => ' . __FUNCTION__ . '()异常：' . $e->getMessage() . '失败信息：' . $e->getFile() . ':' . $e->getLine(), 'error', true);
            return false;
        }
    }

    /**
     * @param array $ids
     * @param array|null $type
     * @param string $sortType
     * @return array
     */
    public function getInfoByIdsInData($ids, $type, $sortType)
    {
        try
        {
            // 获取未删除 的数据
            $data = $this
                ->where(['id' => ['in', $ids]])
                ->column('id,uid,chat_id,type,title,content,data_type,extend,result_data,option_id,pid,create_time,update_time', 'id');
        }
        catch (\Exception $e)
        {
            $data = [];
        }

        return $data;
    }

    public function batchGetInfoByIds($cids, $field = [])
    {
        $resData = parent::batchGetInfoByIds($cids, $field);

        return $this->dataInit($resData);
    }

    /**
     * 数据初始化
     * @param array $data
     * @return array
     */
    public function dataInit(array $data)
    {
        foreach ($data as $index => $itemData)
        {
            $data[$index] = arrayKeyData2int($itemData, ['id', 'uid', 'chat_id', 'type', 'data_type', 'pid', 'create_time', 'update_time']);

            if (isset($itemData['extend']))
            {
                $data[$index]['extend'] = $itemData['extend'] ? json_decode($itemData['extend'], true) : [];
            }

            if (isset($itemData['result_data']))
            {
                $data[$index]['result_data'] = $itemData['result_data'] ? json_decode($itemData['result_data'], true) : [];
            }
        }

        return $data;
    }

    /**
     * 获取列表数据
     * @param int $chatId
     * @param int $limit
     * @param int $maxId
     * @return array
     * @throws \Exception
     */
    public function getPageDatas(int $chatId, int $limit, int $maxId = 0)
    {
        $resData = CacheManage::getInstance()
            ->setCacheConfig($this->cacheModel, $chatId)
            ->setPage(-1)
            ->setSort('desc')
            ->getListPageDataIds(function ($isCache = true, $sortType = 'desc') use ($chatId)
            {
                try
                {
                    $data = $this->where(['chat_id' => $chatId])->order("id {$sortType}")->column('id');

                    $resData = [];
                    foreach ($data as $id)
                    {
                        $resData[$id] = ['id' => $id];
                    }

                    return $resData;
                }
                catch (\Exception $e)
                {
                    return [];
                }
            }, 'id', 0);

        arsort($resData['data']);
        $allIds = array_keys($resData['data']);
        $ids = [];
        $surplusNum = 0;
        foreach ($allIds as $idItem)
        {
            if ($maxId > 0 && $idItem >= $maxId) continue;

            if (count($ids) >= $limit)
            {
                $surplusNum++;
            } else
            {
                $ids[] = $idItem;
            }
        }
        $dataList = $this->batchGetInfoByIds($ids);
        asort($ids);

        $resDataList = [];
        foreach ($ids as $idItem)
        {
            if (isset($dataList[$idItem]))
            {
                $resDataList[] = $dataList[$idItem];
            }
        }

        $resData = [
            'total' => count($allIds),
            'surplus_num' => $surplusNum,
            'data' => $resDataList,
        ];

        return $resData;
    }

    /**
     * 数据 返回样式重组
     * @param array $dataList
     * @return array
     * @throws \Exception
     */
    public function dataListResert(array $dataList)
    {
        $resData = [];
        foreach ($dataList as $k => $dataItem)
        {
            $data = [
                'id' => $dataItem['id'],
                'content' => $dataItem['content'],
                'type' => $dataItem['type'],
                'is_stream_reload' => 0,
            ];
            if (isset($dataItem['extend']['stream']) && $dataItem['extend']['stream'] === 1)
            {
                $data['is_stream_reload'] = 1;
                $data['content'] = '生成失败';
            }

            $resData[] = $data;
        }
        return $resData;
    }

    /**
     * 获取 会话 上下文记录 记录
     * @param int $chatId
     * @param int $chatDetailId
     * @param int $limit
     * @param int $slId
     * @return array
     * @throws \Exception
     */
    public function getChatHistoryList(int $chatId, int $chatDetailId, int $limit = 10, int $slId = 0)
    {
        $pageData = $this->getPageDatas($chatId, $limit, $chatDetailId);

        $violationIds = [];
        foreach ($pageData['data'] as $datum)
        {
            if (isset($datum['extend']['answer_violation'], $datum['pid']) && $datum['extend']['answer_violation'] && $datum['pid'])
            {
                $violationIds[] = $datum['id'];
                $violationIds[] = $datum['pid'];
            }
        }

        $resData = [];
        foreach ($pageData['data'] as $datum)
        {
            if (in_array($datum['id'], $violationIds))
            {
                continue;
            }
            if ($slId > 0 && isset($datum['extend']['sl_id'], $datum['extend']['is_first']) && $datum['extend']['sl_id'] == $slId && $datum['extend']['is_first'] == 1)
            {
                $resData = [];
                if (isset($datum['extend']['is_ignore']) && $datum['extend']['is_ignore'] === 1)
                {
                    continue;
                }
            }

            $resData[] = [
                'role' => $datum['type'] === 1 ? 'assistant' : 'user',
                'content' => $datum['content'],
            ];
        }

        return $resData;
    }
}
